﻿using CKS.Core.Framework;
using Cronos;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ZR.Infrastructure.Helper;

namespace CKS.Schedule
{
    public abstract class CronJobBase : IHostedService, IDisposable
    {
        protected readonly string jobName;

        private readonly CronExpression _expression;
        public bool IsRunning { get; set; }


        public CronJobBase(string JobName, string Cron)
        {
            jobName = JobName;
            _expression = CronExpression.Parse(Cron, CronFormat.IncludeSeconds);

        }





        private async Task WorkAsync(CancellationToken cancellationToken)
        {
            await Task.Yield();
            await Task.Delay(1000);
            var next = _expression.GetNextOccurrence(DateTimeOffset.Now, TimeZoneInfo.Local);
            if (next.HasValue)
            {
                while (IsRunning && !cancellationToken.IsCancellationRequested)
                {
                    next = _expression.GetNextOccurrence(DateTimeOffset.Now, TimeZoneInfo.Local);
                    var delay = next.Value - DateTimeOffset.Now;    //计算出下次任务运行时间
                    if (delay.TotalMilliseconds <= 0)   // prevent non-positive values from being passed into Timer //防止非正值传递到计时器
                    {
                        continue;
                    }
                    try
                    {
                       // LogHelper.MainLogger.Information($"下次执行时间 {next.Value.ToString("yyyy-MM-dd HH:mm:ss")}");
                        await Task.Delay(delay, cancellationToken);
                        if (!cancellationToken.IsCancellationRequested)
                            await ExecuteAsync(cancellationToken);
                        else
                            break;
                    }
                    catch (Exception ex)
                    {
                        LogHelper.WriteError(ex, $"定时任务[{jobName}]执行出现错误");
                    }

                }
            }
            await Task.CompletedTask;
        }





        protected abstract Task ExecuteAsync(CancellationToken cancellationToken);

        public virtual void Dispose()
        {

        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            IsRunning = true;
            LogHelper.Information("Service {JobName} is starting.", jobName);
            Task.Run(()=> WorkAsync(cancellationToken));
            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            IsRunning = false;
            LogHelper.Information("Service {JobName} is stopping.", jobName);

            return Task.CompletedTask;
        }
    }
}
